#pragma once

#include "SemanticModel.h"

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/variant.hpp>

#include <string>
#include <vector>

typedef std::vector<std::wstring> StringVector;

////////////////////////////////////////////////////////////////////////////////
// EmptyItem
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct EmptyItem
	{
	};
}

////////////////////////////////////////////////////////////////////////////////
// OperationsDef
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct SingleOperationDef
	{
		std::wstring OperationName;
		StringVector Participants;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	GenParser::SingleOperationDef,
	(std::wstring, OperationName)
	(StringVector, Participants)
)

////////////////////////////////////////////////////////////////////////////////
// OperationsDef
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct OperationsDef
	{
		std::wstring EssenseName;
		std::vector<SingleOperationDef> Operations;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	GenParser::OperationsDef,
	(std::wstring, EssenseName)
	(std::vector<GenParser::SingleOperationDef>, Operations)
)

////////////////////////////////////////////////////////////////////////////////
// AbstractOperationsDef
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct AbstractOperationsDef
	{
		std::wstring EssenseName;
		std::vector<SingleOperationDef> AbstractOperations;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	GenParser::AbstractOperationsDef,
	(std::wstring, EssenseName)
	(std::vector<GenParser::SingleOperationDef>, AbstractOperations)
)

////////////////////////////////////////////////////////////////////////////////
// GeneralizationDef
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct GeneralizationDef
	{
		std::wstring EssenseName;
		std::wstring SubessenseName;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	GenParser::GeneralizationDef,
	(std::wstring, EssenseName)
	(std::wstring, SubessenseName)
)

////////////////////////////////////////////////////////////////////////////////
// ImplementationDef
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct ImplementationDef
	{
		std::wstring EssenseName;
		std::wstring InterfaceName;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	GenParser::ImplementationDef,
	(std::wstring, EssenseName)
	(std::wstring, InterfaceName)
)

////////////////////////////////////////////////////////////////////////////////
// ContainsDef
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct ContainsDef
	{
		std::wstring EssenseName;
		StringVector PartEssenses;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	GenParser::ContainsDef,
	(std::wstring, EssenseName)
	(StringVector, PartEssenses)
)

////////////////////////////////////////////////////////////////////////////////
// CompositionDef
////////////////////////////////////////////////////////////////////////////////

namespace GenParser
{
	struct CompositionDef
	{
		std::wstring CompositionName;
		StringVector Leafs;
		StringVector Composites;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	GenParser::CompositionDef,
	(std::wstring, CompositionName)
	(StringVector, Leafs)
	(StringVector, Composites)
)

////////////////////////////////////////////////////////////////////////////////
// ModelDef
////////////////////////////////////////////////////////////////////////////////
namespace GenParser
{
	typedef boost::variant<OperationsDef, AbstractOperationsDef, GeneralizationDef,
		EmptyItem, ContainsDef, CompositionDef, ImplementationDef>
		SemanticModelItem;
	typedef std::vector<SemanticModelItem> ModelDef;
}
